﻿using System;
using System.ComponentModel;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Narwhunderful.Aphelia.Framework.Graphics;
using Narwhunderful.Aphelia.Framework.Input;
using Narwhunderful.Aphelia.Framework.Input.Keyboard;

namespace Narwhunderful.Aphelia.Framework.UI
{

    public class HUD : DisposableComponent, IKeyboardComponent
    {

        Game _game;
        public Game Game
        {
            get
            {
                return _game;
            }
            set
            {
                _game = value;
            }
        }

        SpriteBatch _spriteBatch;
        public SpriteBatch SpriteBatch
        {
            get
            {
                return _spriteBatch;
            }
            set
            {
                _spriteBatch = value;
            }
        }

        InputManager _inputManager;
        public InputManager InputManager
        {
            get
            {
                return _inputManager;
            }
            protected set
            {
                _inputManager = value;
            }
        }

        UIComponentCollection<UIScreen> _components = null;
        public UIComponentCollection<UIScreen> Components
        {
            get
            {
                return _components;
            }
            protected set
            {
                _components = value;
            }
        }

        Dictionary<string, UIComponent> _componentNames = new Dictionary<string, UIComponent>();
        public Dictionary<string, UIComponent> ComponentNames
        {
            get
            {
                return _componentNames;
            }
            protected set
            {
                _componentNames = value;
            }
        }

        UIScreen _focusedScreen = null;
        public UIScreen FocusedScreen
        {
            get
            {
                return _focusedScreen;
            }
            protected internal set
            {
                _focusedScreen = value;
            }
        }

        public HUD(Game game, InputManager inputManager)
            : base()
        {
            _game = game;
            _spriteBatch = new SpriteBatch(game.GraphicsDevice);
            _spriteBatch.Tag = false;

            _inputManager = inputManager;
            _inputManager.KeyboardManager.KeyDown += new EventHandler<KeyEventArgs>(OnKeyDown);
            _inputManager.KeyboardManager.KeyPress += new EventHandler<KeyEventArgs>(OnKeyPress);
            _inputManager.KeyboardManager.KeyUp += new EventHandler<KeyEventArgs>(OnKeyUp);
            _inputManager.KeyboardManager.AddKeys(new Keys[] {
                 // arrows
                Keys.Down, Keys.Left, Keys.Right, Keys.Up,
                // alphabet
                Keys.A, Keys.B, Keys.C, Keys.D, Keys.E, Keys.F, Keys.G, Keys.H, Keys.I, Keys.J, Keys.K, Keys.L, Keys.M, Keys.N, Keys.O, Keys.P, Keys.Q, Keys.R, Keys.S, Keys.T, Keys.U, Keys.V, Keys.W, Keys.X, Keys.Y, Keys.Z, 
                // numbers
                Keys.D0, Keys.D1, Keys.D2, Keys.D3, Keys.D4, Keys.D5, Keys.D6, Keys.D7, Keys.D8, Keys.D9, 
                // misc.
                Keys.Back, Keys.Space, Keys.OemPlus, Keys.OemMinus, Keys.OemOpenBrackets, Keys.OemCloseBrackets, Keys.OemQuestion,Keys.OemPeriod,Keys.OemComma, Keys.OemPipe, Keys.OemSemicolon, Keys.OemQuotes, Keys.OemTilde,
            });

            _components = new UIComponentCollection<UIScreen>(this, null, null, _spriteBatch);
        }

        #region IKeyboardComponent

        public event EventHandler<KeyEventArgs> KeyDown = null;
        public event EventHandler<KeyEventArgs> KeyPress = null;
        public event EventHandler<KeyEventArgs> KeyUp = null;

        protected internal virtual void OnKeyDown(object sender, KeyEventArgs e)
        {
            if (KeyDown != null) KeyUp(sender, e);
            if (_focusedScreen != null)
            {
                NavigationDirection direction = NavigationDirection.None;
                switch (e.Keys)
                {
                    case Keys.Up:
                        direction = NavigationDirection.Up;
                        break;
                    case Keys.Down:
                        direction = NavigationDirection.Down;
                        break;
                    case Keys.Left:
                        direction = NavigationDirection.Left;
                        break;
                    case Keys.Right:
                        direction = NavigationDirection.Right;
                        break;
                }
                _focusedScreen.OnKeyDown(this, e);
                if (direction != NavigationDirection.None)
                {
                    if (_focusedScreen == null) return;
                    _focusedScreen.Navigate(direction);
                } 
            }
        }

        protected internal virtual void OnKeyPress(object sender, KeyEventArgs e)
        {
            if (KeyPress != null) KeyPress(sender, e);
            if (_focusedScreen != null) _focusedScreen.OnKeyPress(this, e);
        }

        protected internal virtual void OnKeyUp(object sender, KeyEventArgs e)
        {
            if (KeyUp != null) KeyUp(sender, e);
            if (_focusedScreen != null) _focusedScreen.OnKeyUp(this, e);
        }

        #endregion

        #region IDisposable

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                _inputManager.KeyboardManager.KeyDown -= new EventHandler<KeyEventArgs>(OnKeyDown);
                _inputManager.KeyboardManager.KeyPress -= new EventHandler<KeyEventArgs>(OnKeyPress);
                _inputManager.KeyboardManager.KeyUp -= new EventHandler<KeyEventArgs>(OnKeyUp);
            }
            base.Dispose(disposing);
        }

        #endregion

        public virtual void Update(GameTime gameTime)
        {
            if (_components.UpdatableComponents.Count > 0) _components.Update(gameTime);
        }

        public virtual void Draw(GameTime gameTime)
        {
            if (_components.DrawableComponents.Count > 0) _components.Draw(gameTime);
            if (_focusedScreen != null) _focusedScreen.Draw(gameTime, true);
        }

    }

}
